﻿/*
 * Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://CKFINDER.com/license
 *
 * The software, this file and its contents are subject to the CKFinder
 * License. Please read the license.txt file before using, installing, copying,
 * modifying or distribute this file or part of its contents. The contents of
 * this file is part of the Source Code of CKFinder.
 */

CKFinder.addPlugin('fileeditor', function (api) {
    var regexExt = /^(.*)\.([^\.]+)$/,
        regexTextExt = /^(txt|css|html|htm|js|asp|cfm|cfc|ascx|php|inc|xml|xslt|xsl|cs)$/i,
        regexCodeMirrorExt = /^(css|html|htm|js|xml|xsl|php|cs)$/i,
        codemirror,
        file,
        fileLoaded = false,
        doc;

    var codemirrorPath = CKFinder.getPluginPath('fileeditor') + 'codemirror/';
    var codeMirrorParsers = {
        css: codemirrorPath + 'mode/css/css.js',
        js: codemirrorPath + 'mode/javascript/javascript.js',
        html: [codemirrorPath + 'mode/xml/xml.js', codemirrorPath + 'mode/javascript/javascript.js', codemirrorPath + 'mode/css/css.js', codemirrorPath + 'mode/htmlmixed/htmlmixed.js'],
        xml: codemirrorPath + 'mode/xml/xml.js',
        php: [codemirrorPath + 'mode/xml/xml.js', codemirrorPath + 'mode/javascript/javascript.js', codemirrorPath + 'mode/css/css.js', codemirrorPath + 'mode/clike/clike.js', codemirrorPath + 'mode/php/php.js'],
        c: codemirrorPath + 'mode/clike/clike.js'
    };
    codeMirrorParsers.htm = codeMirrorParsers.html;
    codeMirrorParsers.xsl = codeMirrorParsers.xml;
    codeMirrorParsers.cs = codeMirrorParsers.c;
    codeMirrorParsers.cpp = codeMirrorParsers.c;
    var codeMirrorModes = {
        js: 'javascript',
        htm: 'htmlmixed',
        html: 'htmlmixed',
        xsl: 'xml',
        c: 'clike',
        cs: 'clike',
        cpp: 'clike'
    };

    CKFinder.dialog.add('fileEditor', function (api) {
        var height, width;
        var saveButton = (function () {
            return {
                id: 'save',
                label: api.lang.Fileeditor.save,
                type: 'button',
                onClick: function (evt) {
                    if (!fileLoaded)
                        return true;

                    var dialog = evt.data.dialog;
                    var content = codemirror ? codemirror.getValue() : doc.getById('fileContent').getValue();
                    api.connector.sendCommandPost('SaveFile', null, {
                            content: content,
                            fileName: file.name
                        },
                        function (xml) {
                            if (xml.checkError())
                                return false;

                            api.openMsgDialog('', api.lang.Fileeditor.fileSaveSuccess);
                            dialog.hide();
                            return undefined;
                        },
                        file.folder.type,
                        file.folder
                    );
                    return false;
                }
            };
        })();

        if (api.inPopup) {
            width = api.document.documentElement.offsetWidth;
            height = api.document.documentElement.offsetHeight;
        }
        else {
            var parentWindow = (api.document.parentWindow || api.document.defaultView).parent;
            width = parentWindow.innerWidth ? parentWindow.innerWidth : parentWindow.document.documentElement.clientWidth;
            height = parentWindow.innerHeight ? parentWindow.innerHeight : parentWindow.document.documentElement.clientHeight;
        }

        var cssWidth = parseInt(width, 10) * 0.6 - 10,
            cssHeight = parseInt(height, 10) * 0.7 - 20;

        return {
            title: api.getSelectedFile().name,
            minWidth: parseInt(width, 10) * 0.6,
            minHeight: parseInt(height, 10) * 0.7,
            onHide: function () {
                if (fileLoaded) {
                    var fileContent = doc.getById('fileContent');
                    if (fileContent)
                        fileContent.remove();
                }
            },
            onShow: function () {
                var dialog = this;

                doc = dialog.getElement().getDocument();
                var win = doc.getWindow();
                doc.getById('fileArea').setHtml('<div class="ckfinder_loader_32" style="margin: 100px auto 0 auto;text-align:center;"><p style="height:' + cssHeight + 'px;width:' + cssWidth + 'px;">' + api.lang.Fileeditor.loadingFile + '</p></div>');

                file = api.getSelectedFile();
                var enableCodeMirror = regexCodeMirrorExt.test(file.ext);
                this.setTitle(file.name);

                if (enableCodeMirror && win.$.CodeMirror === undefined)
                    doc.appendStyleSheet(codemirrorPath + 'lib/codemirror.css');

                // If CKFinder is runninng under a different domain than baseUrl, then the following call will fail:
                // CKFinder.ajax.load( file.getUrl() + '?t=' + (new Date().getTime()), function( data )...

                var url = api.connector.composeUrl('DownloadFile', {
                        FileName: file.name,
                        format: 'text',
                        t: new Date().getTime()
                    },
                    file.folder.type, file.folder);

                CKFinder.ajax.load(url, function (data) {
                    if (data === null || (file.size > 0 && data === '')) {
                        api.openMsgDialog('', api.lang.Fileeditor.fileOpenError);
                        dialog.hide();
                        return;
                    }
                    else
                        fileLoaded = true;

                    var fileArea = doc.getById('fileArea');

                    fileArea.setStyle('height', '100%');
                    fileArea.setHtml('<textarea id="fileContent" style="height:' + cssHeight + 'px; width:' + cssWidth + 'px"></textarea>');
                    if (CKFinder.env.opera)
                        doc.getById('fileContent').setHtml(CKFinder.tools.htmlEncode(data));
                    else
                        doc.getById('fileContent').setText(data);

                    codemirror = null;
                    if (enableCodeMirror) {
                        CKFinder.scriptLoader.load(codemirrorPath + 'lib/codemirror.js', function () {
                            CKFinder.scriptLoader.load(codeMirrorParsers[file.ext], function () {
                                codemirror = win.$.CodeMirror.fromTextArea(doc.getById('fileContent').$, {mode: codeMirrorModes[file.ext] || file.ext});

                                // TODO get rid of ugly buttons and provide something better
                                var undoB = doc.createElement('button', {attributes: {'label': api.lang.common.undo}});
                                undoB.on('click', function () {
                                    codemirror.undo();
                                });
                                undoB.setHtml(api.lang.common.undo);
                                undoB.appendTo(doc.getById('fileArea'));

                                var redoB = doc.createElement('button', {attributes: {'label': api.lang.common.redo}});
                                redoB.on('click', function () {
                                    codemirror.redo();
                                });
                                redoB.setHtml(api.lang.common.redo);
                                redoB.appendTo(doc.getById('fileArea'));
                            }, this, false, doc.getHead());
                        }, this, false, doc.getHead());
                    }
                });
            },
            contents: [
                {
                    id: 'tab1',
                    label: '',
                    title: '',
                    expand: true,
                    padding: 0,
                    elements:
                        [
                            {
                                type: 'html',
                                id: 'htmlLoader',
                                html: '' +
                                '<style type="text/css">' +
                                '#fileArea .CodeMirror {background:white}' +
                                '#fileArea .CodeMirror-scroll {height:' + cssHeight + 'px; width:' + cssWidth + 'px}' +
                                '#fileArea .CodeMirror .cm-tab {white-space:pre;}' +
                                // FF >= 12 has some scrolling issue
                                (CKFinder.env.gecko && CKFinder.env.version >= 120000 ? '#fileArea .CodeMirror-scroll > div > div {position:absolute !important}' : '') +
                                '</style>' +
                                '<div id="fileArea"></div>'
                            }
                        ]
                }
            ],
            // TODO http://dev.fckeditor.net/ticket/4750
            buttons: [saveButton, CKFinder.dialog.cancelButton]
        };
    });

    api.addFileContextMenuOption({
            label: api.lang.Fileeditor.contextMenuName,
            command: 'fileEditor'
        }, function (api, file) {
            api.openDialog('fileEditor');
        },
        function (file) {
            var maxSize = 1024;

            if (typeof (CKFinder.config.fileeditorMaxSize) != 'undefined')
                maxSize = CKFinder.config.fileeditorMaxSize;

            // Disable for images, binary files, large files etc.
            if (regexTextExt.test(file.ext) && file.size <= maxSize)
                return file.folder.acl.fileDelete ? true : -1;

            return false;
        });
});
